const { dialog } = require("electron");
// import { getFileIcon } from "@/utils/utls"
const store = require("../../electronStore/index");
const { byteHelper, sizeAdd } = require("../../utils/string");
const { DownloaderHelper } = require("node-downloader-helper");
const fs = require("fs");
const { signature } = require("../../utils/encrypt");
/** ok
 * 打开文件选择框
 * @param oldPath - 上一次打开的路径
 */
async function fileSavePath(win, oldPath = null) {
  // const oldPath = app.getPath('downloads')
  if (!win) return null;
  const options = {
    title: "选择保存位置",
    properties: ["openDirectory", "createDirectory"],
    // defaultPath: oldPath,
  };
  if (oldPath) options.defaultPath = oldPath;
  const { canceled, filePaths } = await dialog.showOpenDialog(win, options);
  return !canceled ? filePaths[0] : null;
}

/** ok
 * 初始化数据结构
 * @param dataList1 客户端下载传递的数据对象(包含下载项和所属项目)
 * @param savePath 保存路径
 */
const initDownloadData = (dataList1, savePath, dialogPath) => {
  // 设置下载项的初始化数据，返回所有文件大小，目的为了计算父项目大小
  const fileSize = dataList1.children.map((item) => {
    // 客户端传递的属性：fileName，url，projectJobId，fileSize
    item.state = 1;
    item.speed = 0;
    item.progress = 0;
    item.savePath = savePath;
    item.filePath = item.filePath || "";
    item.receivedSize =
      item.isReDownload && fs.existsSync(item.filePath)
        ? byteHelper(fs.statSync(item.filePath).size)
        : 0;
    return item.fileSize;
  });
  // 初始化数据
  const downloadData = {
    fileName: dataList1.fileName,
    projectJobId: dataList1.projectJobId,
    children: dataList1.children,
    receivedSize: 0,
    speed: 0,
    progress: 0,
    filePath: savePath,
    savePath: dialogPath,
    state: 1, // 1:等待中 2:下载中 3:暂停 4:已完成 5:已停止 6:失败 7:重试
    fileSize: sizeAdd(fileSize),
  };

  return downloadData;
};

/** ok
 * 下载
 * @param {Object} downloadItem - 下载项
 * @param savePath - 保存路径
 */
const download = (downloadItem, savePath, options) => {
  if (!savePath && !url) return;
  if (!fs.existsSync(savePath)) {
    fs.mkdirSync(savePath);
  }
  options.headers["Ks-Identity"] = signature();
  options.headers["Client-Time"] = new Date().getTime();
  options.httpsRequestOptions["tls"] = { rejectUnauthorized: false };
  if (downloadItem.isReDownload && fs.existsSync(downloadItem.filePath)) {
    options.headers["range"] = `bytes=${
      fs.statSync(downloadItem.filePath).size || 0
    }-`;
    options.resumeIfFileExists = true;
  } else {
    options.headers["range"] = "bytes=0-";
    options.resumeIfFileExists = false;
  }
  return new DownloaderHelper(downloadItem.url, savePath, options);
};

/** ok
 * 获取下载项
 * @param list - 下载记录
 * @param url - 下载项 url
 */
const getDownloadItem = (list, url) => {
  const newData = list.filter((item) => item.url === url);

  if (!newData.length) return null;
  return newData[0].dl || null;
};

/** ok
 * 下载完成，保存数据
 * @param obj - 下载完成的数据(有项目级)
 * @param downLoadComplateList - 下载完成的总数据
 * @param win
 */
const saveData = (obj, downLoadComplateList, win) => {
  return new Promise((resolve, reject) => {
    if (Object.keys(obj).length === 0) return;
    try {
      const index = downLoadComplateList.findIndex(
        (it) => it.projectJobId === obj.projectJobId
      );
      if (index !== -1) {
        obj.children.forEach((child) =>
          downLoadComplateList[index].children.push(child)
        ); // 下载完成的数据
      } else {
        downLoadComplateList.push(obj); // 下载完成的数据
      }
      setDownloadStore(downLoadComplateList);
      resolve(downLoadComplateList);
      // 实时推送传输完成数据
      win.webContents.send("realTransferList", downLoadComplateList);
    } catch (error) {
      reject(error);
    }
  });
};

/**
 * 程序意外关闭时，保存待下载数据到已完成总数据列表
 * @param dataList - 全部待下载数据
 * @param downLoadComplateList - 下载完成的总数据
 */
const saveInterruptData = (dataList, downLoadComplateList) => {
  for (const item of dataList) {
    const index = downLoadComplateList.findIndex(
      (obj) => obj.projectJobId === item.projectJobId
    );
    if (item.children && item.children.length > 0) {
      item.children.forEach((child) => {
        if (child.state !== 4) child.errMsg = "程序关闭导致下载中断";
      });
    }
    if (index === -1) {
      downLoadComplateList.push(item);
    } else {
      downLoadComplateList[index].children = item.children.concat(
        downLoadComplateList[index].children
      );
    }
  }
  dataList = [];

  // 避免打开程序但未登录时关闭程序将上次未完成的下载任务覆盖掉
  if (downLoadComplateList.length === 0)
    downLoadComplateList = getDownloadStore() || [];

  setDownloadStore(downLoadComplateList);
};
/** ok
 * 删除下载完成的数据项
 * @param fileURL - 下载的文件url
 * @param downLoadingList - 并行下载列表
 * @param list - 返回给渲染进程的下载列表
 */
const doneDownloadItem = (fileURL, downLoadingList, dataList) => {
  // 1. 删除单独保存的下载数据项
  const index1 = downLoadingList.findIndex((obj) => obj && obj.url === fileURL);
  if (index1 !== -1) {
    downLoadingList.splice(index1, 1);
  }
  let objComplete = {};
  // 2. 发送给前端的数据项
  dataList.forEach((obj) => {
    if (obj.children && obj.children.length !== 0) {
      const index = obj.children.findIndex((child) => child.url === fileURL);
      if (index !== -1) {
        const child = obj.children.splice(index, 1);
        objComplete = JSON.parse(JSON.stringify(obj));
        objComplete.children = JSON.parse(JSON.stringify(child));
      }
    }
  });
  const index3 = dataList.findIndex((obj) => obj.children.length === 0);
  if (index3 !== -1) {
    dataList.splice(index3, 1);
  }

  return objComplete;
};

/** ok
 * 保存下载记录
 * @param data - 下载项
 */
const setDownloadStore = (data) => {
  store.set("downloadManager", data);
};

/** ok
 * 获取下载记录
 */
const getDownloadStore = () => store.get("downloadManager");

/** ok
 * 暂停或恢复
 * @param downloadItem 前端选择项
 * @param downLoadingList 正在下载列表
 * @param dataList 返回给前端的数据
 * @param downloadObj 父元素本身
 */
const pauseOrResumeFn = (
  downloadItem,
  downLoadingList,
  dataList,
  downloadObj
) => {
  const dl = getDownloadItem(downLoadingList, downloadItem.url);
  if (!dl) return downloadItem;
  // 可以暂停
  const canPauseState = [1, 2];
  if (
    downloadObj
      ? canPauseState.includes(downloadObj.state)
      : canPauseState.includes(downloadItem.state)
  ) {
    dl.pause();
  }
  // 可以恢复
  const canResumeState = [3];
  if (
    downloadObj
      ? canResumeState.includes(downloadObj.state)
      : canResumeState.includes(downloadItem.state)
  ) {
    dl.resume();
  }
};

/** ok
 * 删除
 * @param downloadItem 前端选择项
 * @param downLoadingList 正在下载列表
 * @param dataList 返回给前端的数据
 */
const removeDownloadDataFn = (downloadItem, downLoadingList, dataList) => {
  let dl = getDownloadItem(downLoadingList, downloadItem.url);
  if (dl) {
    // 1. 正在下载的停掉，会进入stop事件里面，删除数据
    dl.stop();
    dl = null;
  } else {
    // 2. 没有正在下载的数据，手动删除
    doneDownloadItem(downloadItem.url, downLoadingList, dataList);
  }
};

/** ok
 * 更新下载中数据
 * @param downloadItem - 更新的下载项
 * @param parentObj - 更新的下载项父元素项目
 * @param stats - 更新的状态信息
 */
const updateDownloadItem = (downloadItem, parentObj, stats) => {
  // 更新下载项
  downloadItem.speed = byteHelper(stats.speed);
  downloadItem.progress = stats.progress.toFixed(1);
  downloadItem.receivedSize = byteHelper(stats.downloaded);
  downloadItem.fileSize = byteHelper(stats.total);
  // 更新下载项父元素
  parentObj.fileSize = sizeAdd(parentObj.children.map((item) => item.fileSize));
  parentObj.receivedSize = sizeAdd(
    parentObj.children.map((item) => item.receivedSize)
  );
  parentObj.speed = sizeAdd(
    parentObj.children
      .filter((item) => item.state === 2)
      .map((item) => item.speed)
  );
  parentObj.progress =
    parentObj.children.reduce(
      (acc, item) => (acc += item.state === 2 && parseFloat(item.progress)),
      0
    ) / parentObj.children.length;
};

/** ok
 * 添加下载项
 * @param downloadInfo - download 事件的信息
 * @param downloadItem - 下载的数据信息
 * @param dl - 下载实例
 */
const addDownloadItem = (downloadInfo, downloadItem, dl) => {
  const info = {
    dl,
    url: downloadItem.url,
    fileSize: byteHelper(downloadInfo.totalSize),
    receivedSize: byteHelper(downloadInfo.downloadedSize),
    fileName: downloadInfo.fileName,
    filePath: downloadInfo.filePath,
    isResumed: downloadInfo.isResumed,
    total: downloadInfo.totalSize,
  };
  downloadItem.filePath = downloadInfo.filePath;
  downloadItem.fileName = downloadInfo.fileName;
  downloadItem.isResumed = downloadInfo.isResumed;
  downloadItem.total = downloadInfo.totalSize;
  return info;
};

/** ok
 * 删除整个项目的文件
 * @param {Object} downloadItem - 项目
 * @param dataList 返回给前端的数据
 */
const removeProjectData = (downloadItem, dataList) => {
  const index = dataList.findIndex(
    (obj) => obj.projectJobId === downloadItem.projectJobId
  );
  if (index !== -1) dataList.splice(index, 1);
};

/** ok
 * 获取总进度
 * @param {Array} dataList 所有的项目文件(客户端展示的)
 */
const updateAllProgress = (dataList) => {
  if (dataList.length === 0) return 0;
  return (
    dataList.reduce((acc, item) => (acc += parseFloat(item.progress)), 0) /
    dataList.length
  );
};

module.exports = {
  fileSavePath,
  initDownloadData,
  download,
  addDownloadItem,
  updateDownloadItem,
  doneDownloadItem,
  saveData,
  setDownloadStore,
  getDownloadStore,
  getDownloadItem,
  pauseOrResumeFn,
  removeDownloadDataFn,
  removeProjectData,
  updateAllProgress,
  saveInterruptData,
};
